package sg.edu.nus.comp.cs4218.impl;

import java.io.File;
import java.util.Vector;

import sg.edu.nus.comp.cs4218.ITool;
import sg.edu.nus.comp.cs4218.extended1.IPipingTool;



public class PipingTool extends ATool implements IPipingTool {
	private File workingDir = null;
	private String stdin;
	private boolean firstTool = true;
	
	/**
	 * Constructor
	 * 
	 * @param tools
	 *            - the tools to be executed
	 */
	public PipingTool(Vector<ITool> tools) {
		super(tools);		
	}

	/**
	 * Execute from tool and use it's output to execute to tool
	 * 
	 * @param from
	 *            - the first tool to be executed
	 * @param to
	 *            - the second tool to be executed using first tool's output
	 * @return Output generated by second tool
	 */
	@Override
	public String pipe(ITool from, ITool to) {
		String result;
		if(from == null || to == null){
			setStatusCode(1);
			return "";
		}
		
		if(stdin != null)
			result = pipe(stdin, from);	
		else
			result = pipe("", from);
		
		// executing from tool gives error, skip executing to tool
		if (from.getStatusCode() != 0) {
			return result;
		}
		return pipe(result, to);

	}

	/**
	 * Execute to tool using stdout as input
	 * If working directory is not specified, use the Shell.workingDir
	 * 
	 * @param stdout
	 *            - input passed to tool
	 * @param to
	 *            - the tool to be executed
	 * @return Output generated by executing tool with stdout as input
	 */
	@Override
	public String pipe(String stdout, ITool to) {
		if(to == null){
			setStatusCode(1);
			return "";
		}
		if(workingDir == null) {
			workingDir = Shell.workingDir;
		}
		String result = to.execute(workingDir, stdout);
		this.setStatusCode(to.getStatusCode());
		return result;
	}

	/**
	 * Execute all tools in order, passing in the output of the earlier tool to the later tool
	 * 
	 * @param workingDir
	 *            - current working directory
	 * @param stdin
	 *            - user input
	 * @return Output generated by the last executing tool
	 */
	@Override
	public String execute(File workingDir, String stdin) {
		String result = "";
		this.workingDir = workingDir;
		this.stdin = stdin;
		firstTool = true;
		int i = 0;
		
		if(tools == null || tools.size() == 0){
			setStatusCode(1);
			return "Invalid input, no tools created";
		}
		
		// if there are 2 tools
		if(tools.size() == 2){
			ITool to = tools.get(i);
			ITool from = tools.get(i+1);
			result = pipe(to, from);
			
			if(to.getStatusCode() != 0 || from.getStatusCode() != 0) // error
				setStatusCode(1);
			else
				setStatusCode(0);
			return result;
		} else {
			// loop each tool
			while(i < tools.size()) {
				if(firstTool) {
					result = pipe(stdin, tools.get(i));
				} else {
					result = pipe(result, tools.get(i));
				}
				firstTool = false;
				if(tools.get(i).getStatusCode() != 0) {// error
					setStatusCode(1);
					return result;
				}
				i++;
			}
		}
		setStatusCode(0);
		return result;
	}
	
}
